package sg.nus.iss.vmcs.gui;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import sg.nus.iss.vmcs.VMCSException;
import sg.nus.iss.vmcs.controllers.MaintenanceController;
import sg.nus.iss.vmcs.gui.elements.ButtonItem;
import sg.nus.iss.vmcs.gui.elements.CoinDisplay;
import sg.nus.iss.vmcs.gui.elements.DrinkDisplay;
import sg.nus.iss.vmcs.gui.elements.FlowItemDisplayStrategy;
import sg.nus.iss.vmcs.gui.elements.LabelledDisplay;
import sg.nus.iss.vmcs.gui.elements.VariableDisplayState;
import sg.nus.iss.vmcs.gui.elements.WarningDisplay;
import sg.nus.iss.vmcs.guilisteners.ExitButtonListener;
import sg.nus.iss.vmcs.guilisteners.PasswordListener;
import sg.nus.iss.vmcs.guilisteners.TotalCashButtonListener;
import sg.nus.iss.vmcs.guilisteners.TransferCashButtonListener;
import sg.nus.iss.vmcs.utils.Constant;
import sg.nus.iss.vmcs.utils.MoneyFormatter;
import sg.nus.iss.vmcs.utils.StoreType;

/**
 * Maintenance Panel for maintenance functionality
 * 
 * @author Olivo Miotto
 * @author Pang Pingli
 */
public class MaintenancePanel extends Dialog {
	
    /** Generated Serial ID */
	private static final long serialVersionUID = 4876678778601367596L;

	public final static         char   WORKING = 'a';
    public final static         char   PSWD = 'b';
    public final static         char   DIALOG = 'c';

    /** Labelled Display for entering passwords */
    private LabelledDisplay password;
    
    /** Warning Display to show if password is valid */
    private WarningDisplay validPswd;
    
    /** Warning Display to show if password is invalid */
    private WarningDisplay invalidPswd;
	
    /** Displays the current coins remaining. May be accessed from other classes */
    private CoinDisplay cDisplay; // need to be access from other class.
    
    /** Displays the current Drinks remaining. May be accessed from other classes */
    private DrinkDisplay dDisplay;  // need to be access from other class.
    
    /** Show Cash in Machine */
    private ButtonItem totalCash;
    
    /** Withdraw All Cash from Machine */
    private Button transferCash;
    
    /** Collected Cash Display */
    private LabelledDisplay collectCash;
    
    /** Exits the Maintenance Panel */
    private Button exitBtn;
   
    /** Maintenance Controller, UI's Controller */
    private MaintenanceController mCtrl;

    public MaintenancePanel (Frame  fr, MaintenanceController mCtrl) {
        super (fr, Constant.MAINTAIN_BANNER, false);

        //Assign Controller
        this.mCtrl = mCtrl;
        
		//Banner
		Panel pnlBanner = new Panel();
		Label lblBanner = new Label(Constant.MAINTAIN_BANNER);
		lblBanner.setFont(Constant.BANNER_FONT);
		pnlBanner.add(lblBanner);
        
        //Password
		Panel pnlPassword = new Panel();
		password = new LabelledDisplay("Password:", 30, new FlowItemDisplayStrategy());
        password.setEchoChar('*');
        password.addListener(new PasswordListener(mCtrl.getAccessManager()));
        pnlPassword.add(password);
        
        Panel pnlPasswordResults = new Panel();
        validPswd = new WarningDisplay("Valid Password");
        validPswd.setVariableDisplayState(VariableDisplayState.getDisplayState(VariableDisplayState.Type.ClearOff));
        validPswd.setDisplay();
        invalidPswd = new WarningDisplay("Invalid Password");
        invalidPswd.setVariableDisplayState(VariableDisplayState.getDisplayState(VariableDisplayState.Type.WarningOff));
        invalidPswd.setDisplay();
        pnlPasswordResults.add(validPswd);
        pnlPasswordResults.add(invalidPswd);
        
        //Center Displays
        cDisplay = new CoinDisplay(mCtrl);
        dDisplay = new DrinkDisplay(mCtrl);
        
        //Total Cash Held
        Panel pnlTotalCash = new Panel();
        totalCash = new ButtonItem(Constant.MAINTAIN_CASH_HELD, new FlowItemDisplayStrategy());
        totalCash.addListener(new TotalCashButtonListener(mCtrl));
        pnlTotalCash.add(totalCash);
        
        //Collect all Cash
        Panel pnlTransferCash = new Panel();
        transferCash = new Button (Constant.MAINTAIN_BTN_COLL);
        transferCash.addActionListener(new TransferCashButtonListener(mCtrl));
        pnlTransferCash.add(transferCash);
        
        //Collected Cash
        collectCash = new LabelledDisplay(Constant.MAINTAIN_LBL_COLL, 5, new FlowItemDisplayStrategy());
        
        //Exit Button
        Panel pnlExit = new Panel();
        exitBtn = new Button(Constant.MAINTAIN_EXIT);
        exitBtn.addActionListener(new ExitButtonListener(mCtrl));
        exitBtn.setFont(Constant.LABEL_FONT);
        pnlExit.add(exitBtn);
        
        //Populating UI
        Panel pnlNorth = new Panel();
        pnlNorth.setLayout(new GridLayout(0, 1));
        pnlNorth.add(pnlBanner);
        pnlNorth.add(pnlPassword);
        pnlNorth.add(pnlPasswordResults);
        
        Panel pnlCenter = new Panel();
        pnlCenter.setLayout(new GridLayout(1, 2));
        pnlCenter.add(cDisplay);
        pnlCenter.add(dDisplay);
        
        Panel pnlSouth = new Panel();
        pnlSouth.setLayout(new GridLayout(0, 1));
        pnlSouth.add(pnlTotalCash);
        pnlSouth.add(pnlTransferCash);
        pnlSouth.add(collectCash);
        pnlSouth.add(pnlExit);
        
        this.setLayout(new BorderLayout());
        this.add(pnlNorth, 	BorderLayout.NORTH);
        this.add(pnlCenter, BorderLayout.CENTER);
        this.add(pnlSouth, 	BorderLayout.SOUTH);
		//this.setResizable(false);
		this.pack();
		addWindowAdapter();
    }

    public void display(){
    	this.setVisible(true);
    }

    public void closeDown () {
        dispose();
    }

    public CoinDisplay getCoinDisplay(){
    	return cDisplay;
    }

    public DrinkDisplay getDrinksDisplay(){
    	return dDisplay;
    }


    public void displayPasswordState(boolean st){
    	if(st)
    		validPswd.setDisplay();
    	else
    		invalidPswd.setDisplay();
    }

    public void setActive(char comp, boolean st){
    	switch (comp){
        	case DIALOG:
        		setActive(PSWD, st);
        		setActive(WORKING, !st);
        		break;
        	case WORKING:
	             collectCash.setActive(st);
	             cDisplay.setActive(st);
	             dDisplay.setActive(st);
	             totalCash.setActive(st);
	             transferCash.setEnabled(st);
	             exitBtn.setEnabled(st);
	             break;
        	case PSWD:
	             password.setActive(st);
	             break;
    	}
    }

    /**
     * Displays the total cash available
     * @param tc
     */
    public void displayTotalCash(int tc){
    	totalCash.setValue(MoneyFormatter.toMoney(tc));
    }

    /**
     * Displays the total coins available
     * @param cc
     */
    public void displayCoins(int cc){
    	collectCash.setValue(cc);
    }

    /**
     *  use when machinery simulator panel changes qty;
     *  It is used to automatically update the displayed quantity in maintenance panel.
     *  It is called by Maintenance Controller
     *  Not required in requirement.
     */
    public void updateQtyDisplay(StoreType type, int idx, int qty) throws VMCSException {
    	if(type == StoreType.CASH) {
    		if(cDisplay.getCurIdx() == idx) {
    			cDisplay.displayQty(idx, qty);
    		}
    	}
    	else {
    		if(dDisplay.getCurIdx() == idx){
    			dDisplay.displayQty(idx, qty);
    		}
    	}
    }

    /**
     * When transfer all button is pushed, the current display needs to be updated.
     * not required in requirement.
     */
    public void updateCurrentQtyDisplay(StoreType type, int qty) throws VMCSException {
    	if(type == StoreType.CASH){
    		updateQtyDisplay(type, cDisplay.getCurIdx(), qty);
    	}
    	else {
    		updateQtyDisplay(type, dDisplay.getCurIdx(), qty);
    	}
    }

    /**
     * Initializes the Collect Cash
     */
    public void initCollectCash(){
    	collectCash.setValue("");
    }

    /**
     * Initializes the total cash
     */
    public void initTotalCash(){
    	totalCash.setValue("");
    }

    /**
     * Clears all passwords
     */
    public void clearPassword(){
    	password.setValue("");
    }

    /**
     * Sets the display price
     * @param price Price to set
     */
    public void displayPrice(int price){
    	dDisplay.getPriceDisplay().setValue(price);
    }

	/**
	 * Adds a window adapter to close down the system
	 */
	private void addWindowAdapter() {
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				if(mCtrl.closeDown() == false)
					return;
				else
					mCtrl.logoutMaintainer();
	        }
		});
	}
}